
--todo: switch to new material system (using pngs)

local function TraceLine(traceData)
	local ret = util.TraceLine(traceData)
	
	debugoverlay.Line(traceData.start, ret.HitPos, 1, Color(200, 200, 255, 255),  true)
	debugoverlay.Cross(ret.HitPos, 10, 1, Color(255, 255, 255, 255), true)
	
	return ret
end

local lightMul = 0	
local lightningStrike = false
local mul1 = 1
local mul2 = 0
local snd1, snd2, emitter, emitter3d;

function createSounds()

	snd1 = CreateSound(LocalPlayer(), Sound("rainscapes/crucial_waterrain_light_loop.wav"))
	snd2 = CreateSound(LocalPlayer(), Sound("rainscapes/interior_rain_med_loop.wav"))
	emitter = ParticleEmitter(LocalPlayer():GetPos())
	emitter3d = ParticleEmitter(LocalPlayer():GetPos(), true)

end
hook.Add( "InitPostEntity", "atmoscreateSounds", createSounds )

local thunderSounds = {
	"rainscapes/thunder_close01.wav",
	"rainscapes/thunder_close02.wav",
	"rainscapes/thunder_close03.wav",
	"rainscapes/thunder_close04.wav",
	"rainscapes/thunder_distant01.wav",
	"rainscapes/thunder_distant02.wav",
	"rainscapes/thunder_distant03.wav",
}

-- materials
local MaterialHorizon = Material( "faloti/sky/sky" );
local MaterialPuff = Material( "faloti/particles/puff" );
local MaterialPuff2 = Material( "faloti/particles/puff2" );
local MaterialSun = Material( "faloti/sky/sun" );
local MaterialSunBurst = Material( "faloti/sky/sunburst" );
local MaterialMoon = Material( "faloti/sky/moon" );
local MaterialStar = Material( "faloti/sky/star" );
local MaterialComet = Material( "faloti/sky/comet" );

-- model we use to render the sky horizon
local HorizonModel = ClientsideModel( "models/zinger/ball.mdl" );
HorizonModel:SetNoDraw( true );
HorizonModel:SetModelScale( Vector( -2500, -2500, -2500 ) );
HorizonModel:SetupBones();

-- convars
local SkyConVar = CreateClientConVar( "cl_atmos_skydetail", "4", true, false );
local NaturePPConVar = CreateClientConVar( "cl_atmos_pp", "1", true, false );

--stuff
local CurrentSky = SKY_DAWN;

local function changesky( len )

	local tbl = { SKY_DAWN, SKY_DAY, SKY_DUSK, SKY_NIGHT, SKY_BLOWOUT }
	local shit = tonumber(net.ReadFloat());

	if( shit > #tbl ) then return end
	if( tbl[shit] == nil ) then return end

	CurrentSky = tbl[shit];

	atmos.CurrentSky = CurrentSky;

end
net.Receive( "atmoschangesky", changesky )

-- different sky types
local Skies = {
	[ SKY_DAWN ] = {
		SkyColor = Color( 102, 156, 190, 255 ),
		HorizonColor = Color( 226, 161, 95, 255 ),
		SunColor = Color( 253, 252, 150, 255 ),
		Elevation = 0,
		CloudColor = Color( 255, 255, 255, 255 ),
		ColorModify = {
			addr = 0.08, addg = 0.04, addb = 0,
			mulr = 0, mulg = 0, mulb = 0,
			color = 1.2,
			contrast = 1,
			brightness = -0.01,
		}
	},
	[ SKY_DAY ] = {
		SkyColor = Color( 132, 186, 220, 255 ),
		HorizonColor = Color( 255, 255, 255, 255 ),
		SunColor = Color( 253, 252, 191, 255 ),
		CloudColor = Color( 255, 255, 255, 255 ),
		Elevation = 20,
		ColorModify = {
			addr = 0, addg = 0, addb = 0,
			mulr = 0, mulg = 0, mulb = 0,
			color = 1.1,
			contrast = 1,
			brightness = 0,
		}
	},
	[ SKY_DUSK ] = {
		SkyColor = Color( 255, 144, 160, 200 ),
		HorizonColor = Color( 231, 92, 0, 255 ),
		SunColor = Color( 253, 225, 139, 255 ),
		CloudColor = Color( 180, 180, 180, 255 ),
		Elevation = 120,
		StarOpacity = 0.25,
		ColorModify = {
			addr = 0.0, addg = 0.035, addb = 0.1,
			mulr = 0, mulg = 0, mulb = 0,
			color = 1.0,
			contrast = 1.0,
			brightness = -0.10,
		}
	},
	[ SKY_NIGHT ] = {
		SkyColor = Color( 0, 0, 0, 255 ),
		HorizonColor = Color( 12, 8, 20, 255 ),
		SunColor = Color( 253, 252, 191, 255 ),
		CloudColor = Color( 140, 140, 140, 235 ),
		Elevation = 210,
		StarOpacity = 1,
		ColorModify = {
			addr = 0.0, addg = 0.05, addb = 0.15,
			mulr = 0, mulg = 0, mulb = 0,
			color = 0.9,
			contrast = 0.8,
			brightness = -0.20,
		}
	},
	[ SKY_STORM ] = {
		SkyColor = Color( 0, 0, 0, 255 ),
		HorizonColor = Color( 12, 8, 20, 255 ),
		SunColor = Color( 253, 252, 191, 0 ),
		CloudColor = Color( 140, 140, 140, 235 ),
		Elevation = 210,
		StarOpacity = 0,
		ColorModify = {
			addr = 0.0, addg = 0.06, addb = 0.17,
			mulr = 0, mulg = 0, mulb = 0,
			color = 0.7,
			contrast = 0.8,
			brightness = -0.18,
		}
	},
	[ SKY_BLOWOUT ] = {
		SkyColor = Color( 0, 0, 0, 255 ),
		HorizonColor = Color( 255, 0, 0, 200 ),
		SunColor = Color( 255, 255, 255, 255 ),
		CloudColor = Color( 140, 140, 140, 0 ),
		Elevation = 40,
		StarOpacity = 0,
		ColorModify = {
			addr = 0.0, addg = 0.05, addb = 0.15,
			mulr = 0, mulg = 0, mulb = 0,
			color = 1.1,
			contrast = 0.7,
			brightness = -0.25,
		}
	},
};

local NextComet = CurTime() + math.Rand( 3, 30 );

local StarColor = Color( 255, 255, 255,255 );
local ShadeColor = Color( 200, 200, 200, 255 );

local ColorMod = {};
local Clouds = {};
local Stars = {};

/*------------------------------------
	GenerateCloudShape()
------------------------------------*/
local function GenerateCloudShape( size )

	local cloud = { { Offset = Vector( 0, 0, 0 ), Frame = 1, Speed = 0.1 } };
	
	-- generate 6 sprites for the cloud, ensure they're spaced at least 48 units apart
	for i = 1, 6 do

		while( true ) do
		
			local valid = false;
		
			-- build a random offset
			local offset = Vector( math.Rand( -( size / 1.5 ), ( size / 1.5 ) ), math.Rand( -( size / 2 ), ( size / 2 ) ), 0 );
			for k, v in pairs( cloud ) do
			
				if( ( v.Offset - offset ):Length() >= ( size / 2 ) ) then
				
					valid = true;
					break;
					
				end
						
			end
			
			-- valid?
			if( valid ) then
			
				-- add to the cloud
				table.insert( cloud, {
					Offset = offset,
					Frame = math.random( 1, 3 ),
					Speed = math.Rand( 0.1, 0.6 ),
					Delta = 0,
				} );
				
				break;
				
			end
		
		end
		
	end
	
	return cloud;
	
end


/*------------------------------------
	GenerateClouds()
------------------------------------*/
local function GenerateClouds()

	-- ensure we get a random distribution EVERY time
	math.randomseed( SysTime() );

	-- generate clouds
	for i = 1, SKY_NUM_CLOUDS do
	
		local size = math.random( 1500, 1800 );
	
		-- generate a random cloud shape
		local shape = GenerateCloudShape( size );
		
		-- calculate cloud elevation and speed
		local elevation = math.random( 0, 15 );
		local speed = math.Rand( -3, -1 );
		speed = speed * ( 0.7 - ( ( 1 / 85 ) * ( elevation - 14 ) ) );
		
		-- cloud bearing angle
		local bearing = ( 360 / SKY_NUM_CLOUDS ) * ( i - 1 );
		
		-- add cloud to list
		table.insert( Clouds, {
			Size = size,
			Shape = shape,
			Speed = speed,
			Angle = Angle( -(elevation + math.random(1,30)), bearing, 0 ),
		} );
		
	end

end


/*------------------------------------
	GenerateStars()
------------------------------------*/
local function GenerateStars()

	-- generate 120 stars
	for i = 1, 120 do
	
		local size = math.random( 100, 150 );
		
		-- calculate star elevation
		local elevation = math.random( -10, 80 );
		
		-- star bearing angle
		local bearing = math.random( 0, 360 );
		
		local angle = Angle( -elevation, bearing, 0 );
		local normal = angle:Forward();
		local position = normal * 14000;
		normal = ( vector_origin - position ):GetNormal();
		
		-- add star to list
		table.insert( Stars, {
			Size = size,
			Normal = normal,
			Position = position,
			TwinkleRate = math.Rand( 1, 2 ),
		} );
		
	end

end


local Comet;


/*------------------------------------
	RenderStars()
------------------------------------*/
function atmos.RenderStars( opacity )

	render.SetMaterial( MaterialStar );
	
	-- render the stars
	mesh.Begin( MATERIAL_QUADS, #Stars );
	for i = 1, #Stars do
	
		local star = Stars[ i ];

		StarColor.a = ( 155 + math.sin( CurTime() * star.TwinkleRate ) * 100 ) * opacity;
		mesh.QuadEasy( star.Position, star.Normal, star.Size, star.Size, StarColor );
		
	end
	mesh.End();
	
	if ( Comet == nil ) then
	
		if( NextComet <= CurTime() ) then
		
			NextComet = CurTime() + math.Rand( 3, 30 );
	
			local angle = Angle( math.random( 20, 40 ) * -1, math.random( 0, 360 ), 0 );
			local normal = angle:Forward();
			local position = normal * 13000;
			normal = ( vector_origin - position ):GetNormal();
			
			Comet = {
				Angle = Angle( math.random( 20, 40 ) * -1, math.random( 0, 360 ), 0 ),
				Alpha = 1,
			};
			
			if ( math.random( 1, 2 ) == 1 ) then
			
				Comet.Direction = -1
				
			else
			
				Comet.Direction = 1
			
			end
			
		end
		
	else
	
		Comet.Alpha = math.Approach( Comet.Alpha, 255, FrameTime() * 100 );
		Comet.Angle = Comet.Angle + Angle( ( FrameTime() * 45 ), ( ( FrameTime() * 45 ) * 2 ) * Comet.Direction, 0 )
		Comet.Normal = Comet.Angle:Forward();
		Comet.Position = Comet.Normal * 13000;
		Comet.Normal = ( vector_origin - Comet.Position ):GetNormal();
		
		render.SetMaterial( MaterialComet );
		
		mesh.Begin( MATERIAL_QUADS, 1 );
		
		mesh.QuadEasy( Comet.Position, Comet.Normal, 1500, 150, Color( 255, 255, 255, Comet.Alpha * opacity ), ( Comet.Direction == 1 ) && 217.5 || 337.5 );
		
		mesh.End();
		
		if ( Comet.Angle.p > 10 ) then
		
			Comet = nil;
		
		end
		
	end
	
end


/*------------------------------------
	RenderCelestialBodies()
------------------------------------*/
function atmos.RenderCelestialBodies( percent, origin )
	
	--if( atmos.Storming ) then return end
	
	local elevation = Skies[ atmos.GetSky() ].Elevation;
			
	-- should render the sun?
	if( atmos.GetSky() != SKY_NIGHT ) then
	
		local time = CurTime();
		
		local normal = Angle( -( elevation + 25 ), 0, 0 ):Forward();
		local position = normal * 14000;
		normal = ( origin - position ):GetNormal();
		
		-- sun color
		local SunColor = Skies[ atmos.GetSky() ].SunColor;
		
		-- render the sun rays
		render.SetMaterial( MaterialSunBurst );
		render.DrawQuadEasy( position, normal, 6000, 6000, Color( SunColor.r, SunColor.g, SunColor.b, 200 ), time * 2 );
		render.DrawQuadEasy( position, normal, 6000, 6000, Color( SunColor.r, SunColor.g, SunColor.b, 200 ), time * -2 );
		render.DrawQuadEasy( position, normal, 12000, 12000, Color( SunColor.r, SunColor.g, SunColor.b, 128 ), time * -4 );
		
		-- render the sun body
		render.SetMaterial( MaterialSun );
		render.DrawQuadEasy( position, normal, 4000, 4000, Color( SunColor.r, SunColor.g, SunColor.b, 255 ) );
	
	-- should render the moon?
	else
	
		local normal = Angle( -( elevation - 180 ), 0, 0 ):Forward();
		local position = normal * 14000;
		normal = ( origin - position ):GetNormal();
		
		-- render the moon glow
		--render.SetMaterial( MaterialSun );
		--render.DrawQuadEasy( position, normal, 3000, 3000, color_white );
		
		-- render the moon
		render.SetMaterial( MaterialMoon );
		render.DrawQuadEasy( position, normal, 3000, 3000, color_white, 90 );
		
	end
	
end


/*------------------------------------
	RenderClouds()
------------------------------------*/
function atmos.RenderClouds( percent, origin )
	
	-- cloud color
	local CloudColor = Skies[ atmos.GetSky() ].CloudColor;
	local mat = MaterialPuff;
	
	if( atmos.GetSky() == SKY_NIGHT ) then
	
	mat = MaterialPuff2;
	
	else
	
	mat = MaterialPuff;
	
	end
	
	render.SetMaterial( mat );

	-- render the outline pass
	mesh.Begin( MATERIAL_QUADS, SKY_NUM_CLOUDS * 6 * 3 );
	for i = 1, SKY_NUM_CLOUDS do
	
		local cloud = Clouds[ i ];
				
		local normal = cloud.Angle:Forward();
		local position = normal * 14000;
		normal = ( origin - position ):GetNormal();
		local right = normal:Angle():Right();
		local up = normal:Angle():Up();
		
		-- animate the cloud
		cloud.Angle.y = cloud.Angle.y + FrameTime() * cloud.Speed + FrameTime() * ( cloud.Speed < 0 && -0.7 || 0.7 );
				
		--
		-- do the caching of the normal and stuff in this pass.	
		--
		
		cloud.Normal = normal;
		cloud.Position = position;
		
		-- render background
		for j = 1, 6 do
		
			local sprite = cloud.Shape[ j ];
		
			sprite.Position = position + right * sprite.Offset.x + up * sprite.Offset.y;
			sprite.Delta = math.sin( CurTime() * sprite.Speed ) * 256;
				
			mesh.QuadEasy(
				sprite.Position,
				normal,
				cloud.Size + sprite.Delta + 256, cloud.Size + sprite.Delta + 256,
				color_black
			);
		
		end
				
		-- render shade
		for j = 1, 6 do
		
			local sprite = cloud.Shape[ j ];
		
			mesh.QuadEasy(
				sprite.Position,
				normal,
				cloud.Size + sprite.Delta, cloud.Size + sprite.Delta,
				ShadeColor
			);
		
		end
		
		-- render color
		for j = 1, 6 do
		
			local sprite = cloud.Shape[ j ];
	
			mesh.QuadEasy(
				position + right * sprite.Offset.x + up * ( sprite.Offset.y + ( cloud.Size * 0.075 ) ),
				normal,
				( cloud.Size + sprite.Delta ) * 0.9, ( cloud.Size + sprite.Delta ) * 0.8,
				CloudColor
			);
		
		end
	
	end
	mesh.End();	

end


/*------------------------------------
	RenderSkyScreenspaceEffects()
------------------------------------*/
local NextInsideCheck = CurTime()+10;

function atmos.RenderSkyScreenspaceEffects()

	if ( NaturePPConVar:GetInt() <= 0 ) then
	
		return;
		
	end
	
	if render.GetDXLevel() < 80 then return end
	
	if( CurTime() > NextInsideCheck ) then
	
		local traced = {}
		traced.start = LocalPlayer():GetPos()
		traced.endpos = LocalPlayer():GetPos()+Vector(0,0,700)
		traced.mask = MASK_NPCWORLDSTATIC
		local tr=util.TraceLine(traced)
		
		if tr.HitWorld then
			atmos.Inside = true;
		else
			atmos.Inside = false;
		end
		
		NextInsideCheck = CurTime()+5;
	
	end
	
	-- need to setup a nice transition between colormods when going indoor/outdoor and from dawn->day->dusk->night
	
	--if atmos.Inside then return end
	--if atmos.Storming then return end
	
	local currentSky = Skies[ atmos.GetSky() ].ColorModify;
	
	-- draw color modification
	ColorMod[ "$pp_colour_addr" ] = currentSky.addr;
	ColorMod[ "$pp_colour_addg" ] = currentSky.addg;
	ColorMod[ "$pp_colour_addb" ] = currentSky.addb;
	ColorMod[ "$pp_colour_brightness" ] = currentSky.brightness
	
	ColorMod[ "$pp_colour_contrast" ] = currentSky.contrast;
	ColorMod[ "$pp_colour_colour" ] = currentSky.color;
	ColorMod[ "$pp_colour_mulr" ] = currentSky.mulr;
	ColorMod[ "$pp_colour_mulg" ] = currentSky.mulg;
	ColorMod[ "$pp_colour_mulb" ] = currentSky.mulb;
	
	DrawColorModify( ColorMod );

end

/*------------------------------------
	PreDrawSkyBox()
------------------------------------*/
function atmos.PreDrawSkyBox()
	
	if ( atmos.Storming == true ) then return end
	
	if ( SkyConVar:GetInt() < 0 ) then
	
		return;
		
	end

	--local pre = gcinfo();

	local angles = atmos.LastSceneAngles;

	local SkyColor = Skies[ atmos.GetSky() ].SkyColor;
	local HorizonColor = Skies[ atmos.GetSky() ].HorizonColor;
	local StarOpacity = Skies[ atmos.GetSky() ].StarOpacity;
		
	-- clear to the sky color
	render.Clear( SkyColor.r, SkyColor.g, SkyColor.b, 255 );
	cam.Start3D( vector_origin, angles )

		-- render the horizon
		
		if( atmos.CanHorizon( game.GetMap() ) ) then
		
			render.SuppressEngineLighting( true );
			render.SetColorModulation( HorizonColor.r / 255, HorizonColor.g / 255, HorizonColor.b / 255 );
			render.MaterialOverride( MaterialHorizon );
					
				HorizonModel:DrawModel();
				
			render.MaterialOverride();
			render.SetColorModulation( 1, 1, 1 );
			render.SuppressEngineLighting( false );
		
		end
		
		-- adhere to sky level of detail
		if( SkyConVar:GetInt() > 2 && StarOpacity && StarOpacity > 0 ) then
		
			-- draw stars
			atmos.RenderStars( StarOpacity );
			
		end
		
		-- adhere to sky level of detail
		if( SkyConVar:GetInt() > 0 ) then
		
			-- draw sun and moon
			atmos.RenderCelestialBodies( percent, vector_origin );
			
		end
		
		-- adhere to sky level of detail
		if( SkyConVar:GetInt() > 1 ) then
		
			-- draw clouds
			atmos.RenderClouds( percent, vector_origin );
			
			-- the clouds create a bunch of garbage- lets clean some of it up
			-- TODO: fix the garbage? not even sure if its possible with all
			-- the calculations involved!!!!
			--collectgarbage( "step", 90 );
			
		end
	
	cam.End3D();
	
	return true;

end

/*------------------------------------
	GetCloudShadeColor()
------------------------------------*/
function atmos.GetCloudShadeColor()

	return ShadeColor;

end


/*------------------------------------
	GetCloudColor()
------------------------------------*/
function atmos.GetCloudColor()

	return Skies[ atmos.GetSky() ].CloudColor;

end

function atmos.GetSky()
	
	if( atmos.Storming ) then
	
		return SKY_STORM;
		
	end
	
	return CurrentSky;
	
end

-- generate the universe!!!1
GenerateClouds();
GenerateStars();

-- storming/raining stuff
atmos.NextThunder = 0;

function atmos.BeginStorm()

	if( !atmos.CanStorm(game.GetMap()) ) then return end
	
	atmos.Storming = true;
	
	hook.Remove( "PreDrawSkyBox", "AtmosPDSB" );
	
end

function atmos.StopStorm()
	
	if( !atmos.CanStorm(game.GetMap()) ) then return end
	
	atmos.Storming = false;
	atmos.NextThunder = 0;
	
	hook.Add( "PreDrawSkyBox", "AtmosPDSB", atmos.PreDrawSkyBox );
	
end

-- debug
concommand.Add( "cl_atmos_storm", function( pl, cmd, args ) if( atmos.Storming ) then atmos.StopStorm() else atmos.BeginStorm() end end );

function atmos.StormThink()

	if( !atmos.Storming ) then return end
	
	if( CurTime() > atmos.NextThunder ) then
		
		atmos.NextThunder = CurTime() + 20 + math.random( 5, 45 );

		lightMul = math.Rand(0.5,1)
	
		timer.Simple(math.Rand(0.5,2), function()
		
			local snd = thunderSounds[math.random(1,#thunderSounds)]
			
			LocalPlayer():EmitSound(snd)
			
		end)
	
		lightningStrike = true
	
	end

end
hook.Add( "Think", "AtmosStormThink", atmos.StormThink );

function atmos.RecvStorm( len )

	local bool = net.ReadFloat();
	
	if( bool == 0 ) then
	
		atmos.StopStorm();
		
	else
	
		atmos.BeginStorm();
		
	end
	
end
net.Receive( "atmosrecvstorm", atmos.RecvStorm );



local mat = Material( "models/debug/debugwhite" )

local mat = CreateMaterial( "WhiteMaterial", "UnlitGeneric", {	-- Necessary to assign color by vertex
	["$basetexture"] = "color/white",
	["$vertexcolor"] = 1,	-- Necessary to assign color by vertex
	["$vertexalpha"] = 1,	-- Necessary to assign alpha to vertex
	["$model"] = 1
} );

local lightning = 
{
	{
		rad = 0,
		segments = {
			Vector(100,0,0),
			Vector(0,100,0),
			Vector(-25,50,0)
		},
		life = 1
	}
}

local nextCloudEmit = 0
hook.Add("PostDrawSkyBox", "Rain PostDrawSkyBox", function()
	
	if( atmos.Storming == false ) then return true end
	
	lightMul = math.Approach(lightMul, 0, FrameTime() * 3)
	
	local alpha = 200 + (55 * lightMul)
	cam.Start3D(LocalPlayer():EyePos(),LocalPlayer():EyeAngles())
		render.SuppressEngineLighting(true)
		
		local light = 255 * lightMul
		
		render.SetMaterial( mat )
		render.DrawQuadEasy( Vector(0,0,10240),    --position of the rect
			Vector(0,0,-1),        --direction to face in
			20480, 20480,              --size of the rect
			Color( light, light, light, alpha ),  --color
			90                     --rotate 90 degrees
		)
		render.SetMaterial( mat )
		render.DrawQuadEasy( Vector(0,10240,0),    --position of the rect
			Vector(0,-1,0),        --direction to face in
			20480, 20480,              --size of the rect
			Color( light, light, light, alpha ),  --color
			90                     --rotate 90 degrees
		)
		render.SetMaterial( mat )
		render.DrawQuadEasy( Vector(0,-10240,0),    --position of the rect
			Vector(0,1,0),        --direction to face in
			20480, 20480,              --size of the rect
			Color( light, light, light, alpha ),  --color
			90                     --rotate 90 degrees
		)
		render.SetMaterial( mat )
		render.DrawQuadEasy( Vector(10240,0,0),    --position of the rect
			Vector(-1,0,0),        --direction to face in
			20480, 20480,              --size of the rect
			Color( light, light, light, alpha ),  --color
			90                     --rotate 90 degrees
		)
		render.SetMaterial( mat )
		render.DrawQuadEasy( Vector(-10240,0,0),    --position of the rect
			Vector(1,0,0),        --direction to face in
			20480, 20480,              --size of the rect
			Color( light, light, light, alpha ),  --color
			90                     --rotate 90 degrees
		)
		render.SuppressEngineLighting(false)
		
	
		
	cam.End3D()
	
	if( nextCloudEmit < CurTime() ) then
	
		p = emitter3d:Add("particle/smokesprites_000" .. math.random(1,9), Vector(math.Rand(-8000,8000),math.Rand(-8000,8000),5000))
		p:SetColor(50, 50, 50)
		p:SetLifeTime(0)
		p:SetDieTime(30)
		p:SetStartSize(10500)
		p:SetEndSize(0)
		p:SetStartAlpha(0)
		p:SetEndAlpha(180)
		p:SetRoll(math.Rand(0,360))
		p:SetAngles(Angle(90,0,0))
		
		nextCloudEmit = CurTime() + 0.3
		
	end
	
	if( lightningStrike ) then
	
		lightningStrike = false
		
		p = emitter3d:Add("particle/smokesprites_000" .. math.random(1,9), Vector(math.Rand(-8000,8000),math.Rand(-8000,8000),4900))
		p:SetColor(255, 255, 255)
		p:SetLifeTime(0)
		p:SetDieTime(0.1)
		p:SetStartSize(5500)
		p:SetEndSize(0)
		p:SetStartAlpha(255)
		p:SetEndAlpha(0)
		p:SetRoll(math.Rand(0,360))
		p:SetAngles(Angle(90,0,0))
		
	end
	
end)


hook.Add("Tick", "SoundMod", function()

	if( atmos.Storming == false ) then return end
	
	snd1:ChangeVolume(mul1)
	snd2:ChangeVolume(mul2)
	
	local td = {}
	td.start = LocalPlayer():GetPos()
	td.endpos = td.start + Vector(0,0,100000)
	td.filter = LocalPlayer()

	-- Rain
	local p = nil
	
	for i=1,40 do
		p = emitter:Add("particle/snow", LocalPlayer():GetPos() + (LocalPlayer():GetVelocity() * 0.5) + Vector(math.random(-1500, 1500),math.random(-1500, 1500),1500))
		p:SetCollide(true)
		p:SetLifeTime(0)
		p:SetDieTime(4)
		p:SetStartSize(1)
		p:SetStartAlpha(255)
		p:SetEndAlpha(255)
		p:SetStartLength(50)
		p:SetEndLength(50)
		p:SetVelocity(Vector(0,0,-3000))
		
		p:SetCollideCallback(function(part, hitpos, hitnormal)
			for i2=1,2 do
				p = emitter:Add("particle/snow", hitpos)
				p:SetLifeTime(0)
				p:SetDieTime(math.Rand(0.10, 0.50))
				p:SetStartSize(1)
				p:SetStartAlpha(255)
				p:SetEndAlpha(0)
				p:SetStartLength(5)
				p:SetEndLength(0)
				p:SetVelocity(Vector(0,0,10) + (VectorRand() * 5))
				p:SetGravity(Vector(0,0,-100))
			end
			
			if(math.random(0,70) == 0) then
				local Size = math.Rand(180,480)
				p = emitter:Add("particle/smokesprites_000" .. math.random(1,9), hitpos + (hitnormal * Size))
				p:SetLifeTime(0)
				p:SetDieTime(math.Rand(4, 10))
				p:SetStartSize(Size)
				p:SetEndSize(math.Rand(180,480))
				p:SetStartAlpha(10)
				p:SetEndAlpha(0)
				p:SetRoll(math.random(0,360))
				p:SetRollDelta(math.Rand(-0.2,0.2))
				-- p:SetVelocity((VectorRand() * 50))
				
				td = {}
				td.start = hitpos
				td.endpos = td.start + ((LocalPlayer():GetPos() + Vector(0,0,60)) - hitpos)
				td.filter = LocalPlayer()
				local tr = TraceLine(td)
				local pitch = 70
				
				if(tr.Entity == NullEntity() or tr.Entity == nil) then
					pitch = 100
				end
				
				WorldSound("rain".. math.random(1,4) ..".wav", hitpos, 75, pitch)
			end
			part:SetDieTime(0)
		end)
	end
end)

print("\n[atmos] cl_nature loaded.");